use rust_xlsxwriter::{Format, Workbook};

use crate::{ExportAction, Info, SqlConfig};

pub(crate) struct Excel {}

impl ExportAction for Excel {
    fn run(
        config: &crate::SqlConfig,
        groups: &std::collections::BTreeMap<&String, Vec<&crate::Info>>,
    ) -> Result<String, crate::RunError> {
        let name = get_output(config);
        let mut workbook = Workbook::new();
        let bold_format = Format::new().set_bold();
        groups.iter().for_each(|(name, list)| {
            let worksheet = workbook.add_worksheet();
            worksheet.set_name(*name).unwrap();
            worksheet
                .write_with_format(0, 0, "序号", &bold_format)
                .unwrap();
            worksheet
                .write_with_format(0, 1, "列名", &bold_format)
                .unwrap();
            worksheet
                .write_with_format(0, 2, "数据类型", &bold_format)
                .unwrap();
            worksheet
                .write_with_format(0, 3, "为Null", &bold_format)
                .unwrap();
            worksheet
                .write_with_format(0, 4, "备注", &bold_format)
                .unwrap();
            list.iter().enumerate().for_each(|(index, info)| {
                let Info {
                    ordinal_position,
                    data_type,
                    is_nullable,
                    column_name,
                    column_comment,
                    ..
                } = info;
                let column_comment = column_comment.as_ref().map_or("", |v| v.as_str());
                let index = index + 1;
                worksheet.write(index as u32, 0, *ordinal_position).unwrap();
                worksheet.write(index as u32, 1, column_name).unwrap();
                worksheet.write(index as u32, 2, data_type).unwrap();
                worksheet.write(index as u32, 3, is_nullable).unwrap();
                worksheet.write(index as u32, 4, column_comment).unwrap();
            });
        });
        workbook.save(&name).unwrap();
        Ok(name)
    }
}

fn get_output(config: &SqlConfig) -> String {
    let name = config.database.as_str().to_string();
    let name = format!("{name}.xlsx");
    config
        .output
        .as_ref()
        .map(|v| {
            if v.ends_with(".xlsx") {
                v.to_string()
            } else {
                format!("{}.xlsx", v)
            }
        })
        .unwrap_or(name)
}
